﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using MathematicallySafe.Armourer;
using MathematicallySafe.Armourer.Base;
using MathematicallySafe.HeadCounter.Data.Parsers;
using StructureMap;

namespace MathematicallySafe.HeadCounter.Data.Models
{
    [Serializable]
    public class LootTable
    {
        private readonly IArmouryService _armouryService = ArmouryServiceFactory.Instance.GetArmouryService();
        private ItemXmlParser _xmlParser = new ItemXmlParser();

        public event EventHandler<ItemDownloadedEventArgs> ItemDownloaded;

        private readonly object _sync = new object();

        public LootTable()
        {
            Items = new List<LootItem>();
        }

        public void SubscribeEvents()
        {
            _armouryService.ItemDataDownloaded += ArmouryServiceItemDownloaded;
        }

        public void UnsubscribeEvents()
        {
            _armouryService.ItemDataDownloaded -= ArmouryServiceItemDownloaded;
        }

        public List<LootItem> Items { get; set; }

        public LootItem this[string itemName]
        {
            get
            {
                lock (_sync)
                {
                    var item = Items.Where(i => i.Name == itemName).FirstOrDefault();
                    return item;
                }
            }
        }

        public LootItem this[int id]
        {
            get
            {
                lock (_sync)
                {
                    var item = Items.Where(i => i.ID == id).FirstOrDefault();
                    return item;
                }
            }
        }

        public bool HasItem(int id)
        {
            lock (_sync)
            {
                return Items.FirstOrDefault(i => i.ID == id) != null;
            }
        }

        public void DownloadItemAsynch(int id, bool force)
        {
            lock (_sync)
            {
                var item = Items.Where(i => i.ID == id).FirstOrDefault();

                if (item == null || force)
                {
                    _armouryService.EnqueueGetItem(id);
                    _armouryService.RunArmouryServiceAsync();
                }
            }
        }

        void ArmouryServiceItemDownloaded(object sender, ItemDataDownloadedEventArgs e)
        {
            LootItem item; 

            lock (_sync)
            {
                item = _xmlParser.MakeLootItem(e.ItemXml);

                if (item.iLevel >= 200)
                {
                    var match = Items.FirstOrDefault(i => i.ID == item.ID);

                    if (match != null)
                    {
                        Items.Remove(match);
                    }

                    Items.Add(item);
                    Items = (Items.OrderBy(i => i.Name)).ToList();
                }
            }

            if (item != null && ItemDownloaded != null)
            {
                ItemDownloaded(this, new ItemDownloadedEventArgs(item.ID));
            }
        }

    }

    public static class LootTableExtentions
    {
        public static void ProcessLootOverrides(this LootTable lootTable)
        {
            var options = ObjectFactory.GetInstance<IHeadCounterService>().Options;

            lootTable.Items.ForEach(item =>
                                        {
                                            var lootOverride = options.Overrides.FirstOrDefault(o => o.id == item.ID);

                                            if (lootOverride != null)
                                            {
                                                item.Slot = lootOverride.Slot;
                                                item.iLevel = lootOverride.iLevel;
                                            }
                                        });
        }
    }

}